.TITLE XXTTI .IDENT /01.04/ ; ; Copyright (c) 1995-1999 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; ; 03-MAR-87 KAREN NOEL ; ; MODIFIED FOR CPRSX V2.0 BY: ; ; Eric Postpischil 20 Oct 1989 1.04 ; edp076 Move SF.GMC and SF.SMC processing to XXFIN. ; ; Paul K. M. Weiss 28 Jul 1989 01.03 ; pkw182 Don't permanently block task on attach with illegal params ; ; Paul K. M. Weiss 21 Jun 1989 01.02 ; pkw181 Buffer requests smaller than $CPMXB ; ; Eric Postpischil 25 May 1989 01.01 ; edp072 Remove restriction on attaching terminals. ; ; ;+ ; ; ****** X X T T I ****** ; ; THIS MODULE CONTAINS THE ROUTINES TO VALIDATE A NEW I/O REQUEST ; FOR A TERMINAL. THE I/O REQUESTS ARE VALIDATED PRIOR TO PLACING THEM ; IN THE DEVICE'S I/O PACKET QUEUE. THIS MUST OCCUR WHILE THE USER TASK ; WHICH ISSUED THE REQUEST IS STILL THE CURRENT TASK. NEXT, THE REQUEST IS ; PLACED IN THE REQUEST QUEUE FOR THE TERMINAL. ; ;- ; .MCALL PKTDF$,UCBDF$,TCBDF$ PKTDF$ UCBDF$ ,,1 TCBDF$ ; ; LOCAL SYMBOL DEFINITIONS ; MAP5 = 120000 MAP6 = 140000 .PAGE .SBTTL XXTTI - FUNCTION CODE DISPATCH TABLE ; ; DISPATCH TABLE FOR PROCESSING DIFFERENT FUNCTION CODES BEFORE ; ENTERING A PACKET IN THE I/O QUEUE. ; QPDSP: .WORD 0 ;IO.KIL .WORD QPWLB ;IO.WLB .WORD QPRLB ;IO.RLB .WORD QPATT ;IO.ATT .WORD QPDET ;IO.DET .WORD QPSPC ;SPECIAL FUNCTIONS: ; IO.GTS ; SF.SMC ; SF.GMC .WORD QPHNG ;IO.HNG .WORD 0 ;RESERVED EXEC CLOSE-OUT-LUN FUNCTION .WORD 0 ;RESERVED FOR USER MODE DIAGNOSTICS .WORD QPRPR ;IO.RPR .WORD QPRTT ;IO.RTT .IF DF B$$MAP .WORD QPWSD ;IO.WSD .WORD QPRSD ;IO.RSD .ENDC ;B$$MAP .WORD 0 ;IO.EIO .PAGE .SBTTL XXTTI - TERMINAL I/O REQUEST INITIATION ENTRY POINT ; ;+ ; **-XXTTI - VALIDATE I/O PACKET ENTRY POINT. ; ; THIS ROUTINE IS CALLED FROM "XXDRV" WHEN A TASK HAS ISSUED AN I/O REQUEST ; FOR A TERMINAL. THE CALL IS MADE PRIOR TO QUEUEING THE I/O PACKET TO THE ; SCB QUEUE SINCE TERMINALS HAVE THE "UC.QUE" BIT SET IN THEIR UCB'S. THIS ; IS DONE WHILE THE TASK CONTEXT IS STILL VALID, SINCE MANY FUNCTIONS WILL ; NEED ADDITIONAL PARAMETER CHECKS NOT DONE BY THE EXECUTIVE. ; ; INPUTS: ; R1 => I/O REQUEST PACKET TO BE PROCESSED ; R4 => SCB FOR THE REQUESTED TERMINAL ; R5 => UCB FOR THE REQUESTED TERMINAL ; ; OUTPUTS: NONE. ; ; REGISTERS MODIFIED: R0, R1, R3 ;- ; XXTTI:: SAVNR MOV R1,R3 ;COPY I/O PACKET POINTER MOVB I.FCN+1(R3),R0 ;GET THE I/O FUNCTION CODE ASL R0 ;CONVERT IT TO A WORD INDEX CLR -(SP) ;POSSIBLE CPR PACKET FOR ERROR RECOVERY CALLR @QPDSP(R0) ;DISPATCH TO PROCESS THIS REQUEST .PAGE .SBTTL . BUFFER ADDRESS CHECKING AND RELOCATION ROUTINES ; ;+ ; **-CKBFR - ADDRESS CHECK AND LOCK BUFFER FOR READ ACCESS ; **-CKBFRW - ADDRESS CHECK AND LOCK BUFFER FOR READ ACCESS, WORD ALIGNMENT ; **-CKBFW - ADDRESS CHECK AND LOCK BUFFER FOR READ/WRITE ACCESS,WORD ALIGNMENT ; **-CKBFB - ADDRESS CHECK AND LOCK BUFFER FOR READ/WRITE ACCESS ; ; THESE ROUTINES PERFORM THE DESCRIBED ADDRESS CHECKING ON A USER BUFFER. ; ; INPUTS: ; R0 => USER BUFFER (VIRTUAL ADDRESS) ; R1 = LENGTH OF USER BUFFER ; ; OUTPUTS: ; CC-C = 0 IF ADDRESS CHECK WAS SUCCESSFUL ; CC-C = 1 IF ADDRESS CHECK FAILED ; R1 = BIAS OF RELOCATED USER BUFFER ADDRESS ; R2 = DISPLACEMENT OF RELOCATED USER BUFFER ADDRESS IF SUCCESS ; R2 = ERROR CODE FOR ADDRESS CHECK FAILURE REASON: ; "IE.SPC" IF SPECIFIED BUFFER LENGTH IS ZERO ; "IE.SPC" IF BUFFER NOT WORD ALIGNED OR EXEC ADDRESS CHECK FAILS ; "IE.BAD" IF BUFFER SIZE IS GREATER THAN 8128. BYTES ; ; REGISTERS MODIFIED: R0 ;- ; .ENABL LSB CKBFRW: BIT #1,R0 ;DOES BUFFER START ON ODD ADDRESS? BNE 910$ ;IF NE, YES...RETURN INVALID BUFFER ERROR CKBFR:: MOV #$CKBFR,-(SP) ;SET UP CALL FOR READ-ACCESS CHECK BR 10$ ;SKIP TO COMMON CODE CKBFW:: MOV #$CKBFW,-(SP) ;SET UP CALL FOR WRITE-ACCESS CHECK-WORD ALIGNED BR 10$ CKBFB:: MOV #$CKBFB,-(SP) ;SET UP CALL FOR WRITE-ACCESS CHECK 10$: TST R1 ;IS BUFFER SIZE VALID? BEQ 900$ ;IF EQ, NO...RETURN INVALID BUFFER ERROR CMP R1,#20000-100 ;IS BUFFER BIGGER THAN 8128. BYTES? BHI 920$ ;IF HI, YES...RETURN BAD BUFFER SIZE ERROR MOV (SP),-(SP) ;DUPLICATE MAPPING ROUTINE ADDRESS ON STACK MOV @#KISAR6,2(SP) ;SAVE CURRENT EXEC MAPPING MOV $SAHDB,@#KISAR6 ;MAP CURRENT TASK HEADER CALL @(SP)+ ;CALL REQUESTED ADDRESS CHECK ROUTINE MOV (SP)+,@#KISAR6 ;RESTORE PREVIOUS MAPPING BCS 910$ ;IF CS, IT FAILED...RETURN ERROR CALL $RELOC ;RELOCATE ADDRESS AND CONVERT TO DOUBLEWORD RETURN ;ALL DONE 900$: TST (SP)+ ;POP OFF CO-ROUTINE ADDRESS 910$: MOV #IE.SPC&377,R2 ;SET COMPLETION ERROR CODE FOR INVALID BUFFER BR 990$ ;SKIP 920$: TST (SP)+ ;POP OFF CO-ROUTINE ADDRESS MOV #IE.BAD&377,R2 ;SET COMPLETION ERROR CODE FOR BAD SIZE 990$: SEC ;RETURN WITH ERROR FLAG RETURN ;ALL DONE ; ;+ ; **-CPBFW - WRITE CHECK, WORD ALIGNED, BUFFER IN CPRBUF ; **-CPBFRW - READ CHECK, WORD ALIGNED, BUFFER IN CPRBUF ; **-CPBFR - READ CHECK, BUFFER IN CPRBUF ; **-CPBUF - NO ADDRESS CHECKING, READING FROM BUFFER, BUFFER IN CPRBUF ; ; THESE ROUTINES PERFORM THE APPROPRIATE ADDRESS CHECK ON THE BUFFER AND COPY ; THE BUFFER INTO CPRBUF ; ; INPUTS: ; ; R0 USER ADDRESS OF BUFFER ; R1 LENGTH OF BUFFER ; R2 CPR PACKET BIAS ; R3 I/O PACKET ADDRESS ; R4 OFFSET INTO CPRBUF TO START BUFFERING (AS APR6 OFFSET) ; R5 UCB ADDRESS ; ; OUTPUTS: ; ; CC-C = 0 IF ADDRESS CHECK WAS SUCCESSFUL ; CC-C = 1 IF ADDRESS CHECK FAILED ; R1 CPR PACKET BIAS ; R2 OFFSET INTO CPRBUF OF BEGINNING OF BUFFER IF SUCCESS ; R2 = ERROR CODE FOR ADDRESS CHECK FAILURE REASON: ; "IE.SPC" IF SPECIFIED BUFFER LENGTH IS ZERO ; "IE.SPC" IF BUFFER NOT WORD ALIGNED OR EXEC ADDRESS CHECK FAILS ; "IE.BAD" IF BUFFER SIZE IS GREATER THAN 8128. BYTES ; P$LUN+32 IN CPR PACKET - USER ADDRESS OF BUFFER ; R3, R5, APR6 MAPPING PRESERVED ;- CPBFW: MOV #$CKBFW,-(SP) ;ADDRESS CHECK ROUTINE BR 110$ ;CONTINUE IN COMMON CPBFRW: BIT #1,R0 ;DOES BUFFER START ON ODD ADDRESS? BNE 910$ ;IF NE, YES...RETURN INVALID BUFFER CPBFR: MOV #$ACHRO,-(SP) ; BR 110$ ;CONTINUE IN COMMON CPBUF: MOV #130$,-(SP) ;NO ADDRESS CHECKING 110$: TST R1 ;IS BUFFER SIZE VALID? BEQ 900$ ;IF EQ, NO...RETURN INVALID BUFFER ERROR CMP R1,#20000-100 ;IS BUFFER BIGGER THAN 8128. BYTES? BHI 920$ ;IF HI, YES...RETURN BAD BUFFER SIZE SUB #6,SP ;GET SPACE ON STACK TO SAVE THINGS MOV 6(SP),(SP) ;COPY ADDRESS OF ROUTINE TO CALL MOV @#KISAR6,2(SP) ;SAVE CURRENT EXEC MAPPING, MOV R2,4(SP) ;CPR PACKET BIAS, MOV R1,6(SP) ;AND SIZE OF TRANSFER MOV $SAHDB,@#KISAR6 ;MAP CURRENT TASK HEADER CALL @(SP)+ ;CALL REQUESTED ADDRESS CHECK ROUTINE MOV (SP)+,@#KISAR6 ;RESTORE PREVIOUS MAPPING MOV (SP)+,R2 ;RESTORE CPR PACKET BIAS MOV (SP)+,R1 ;RESTORE SIZE OF TRANSFER BCS 910$ ;IF CS, IT FAILED...RETURN ERROR MOV R3,-(SP) ;SAVE THE I/O PACKET MOV R4,-(SP) ;SAVE BUFFER OFFSET MOV R1,-(SP) ;SAVE THE LENGTH MOV R2,R3 ;MOVE CPR BIAS CALL $RELOC ;RELOCATE ADDRESS MOV (SP),R0 ;RESTORE LENGTH MOV @#KISAR6,(SP) ;SAVE APR6 MAPPING MOV R3,@#KISAR6 ;MAP THE CPR PACKET MOV R1,MAP6+P$LUN+32 ;STORE BIAS IN PACKET MOV R2,MAP6+P$LUN+34 ;AND OFFSET MOV (SP)+,@#KISAR6 ;RESTORE APR6 MAPPING SUB #20000,R2 ;MAKE USER OFFSET INTO APR5 OFFSET CALL $BLXIO ;COPY THE BUFFER MOV R3,R1 ;MOVE PACKET BIAS FOR OUTPUT MOV (SP)+,R2 ;STARTING OFFSET OF BUFFER IN PACKET MOV (SP)+,R3 ;RESTORE I/O PACKET BIC #170000,R2 ;OFFSET SHOULD NOT INCLUDE APR BIAS 130$: CLC RETURN ;ALL DONE .DSABL LSB .PAGE .SBTTL . WRITE REQUEST PROCESSING .SBTTL . QPWSB - WRITE SPECIAL DATA ; ;+ ; **-QPWSD - WRITE SPECIAL DATA (IO.WSD) ;- ; .IF DF B$$MAP QPWSD:: BIC #^C,I.FCN(R3) ;CLEAR DISALLOWED BITS BIS #TF.WAL,I.FCN(R3) ;SET REQUIRED BIT CMP #T.RSDN,I.PRM+10(R3) ;IS THE DATA TYPE SPECIFIER LEGAL? BLO EQPBAD ;NO,RETURN REQUEST WITH BAD PARAMENTERS ; ; FALL THROUGH TO QPWLB ; .ENDC ;B$$MAP .SBTTL . QPWLB - WRITE LOGICAL BLOCK ; ;+ ; **-QPWLB - NORMAL WRITE REQUEST (IO.WLB) ;- ; QPWLB:: MOV #1,R4 ;INDICATING ONE BUFFER IN FIRST PARAMETER BITB #TF.WBT,I.FCN(R3) ;IS THIS A BREAKTHROUGH WRITE REQUEST? BEQ CKBFLN ;IF EQ, NO...CHECK BUFFER LENGTH AND QUEUE IT MOV I.TCB(R3),R0 ;GET ISSUEING TASK TCB BIT #T3.PRV!T3.CLI,T.ST3(R0) ;IS TASK PRIVILEGED OR A CLI? BNE 10$ ;IF NE, YES...DO BREAKTHROUGH CMP T.UCB(R0),R5 ;IS THE IO.WBT TO OWN TI:? BNE EQPPRI ;IF NOT, DON'T ALLOW IT 10$: MOVB #251.,I.PRI(R3) ;CHANGE REQUEST TO PRIORITY 251. BIS #TF.CCO,I.FCN(R3) ;BREAKTHROUGH IMPLIES CANCEL CONTROL-O BR CKBFLN ;CHECK BUFFER LENGTH AND QUEUE THE REQUEST .PAGE .SBTTL . READ REQUEST PROCESSING .SBTTL . QPRSD - READ SPECIAL DATA ; ;+ ; **-QPRSD - READ SPECIAL DATA REQUEST (IO.RSD) ;- ; .IF DF B$$MAP QPRSD:: BIC #^C,I.FCN(R3) ;CLEAR DISALLOWED BITS BIS #,I.FCN(R3) ;FORCE REQUIRED BITS TST I.PRM+10(R3) ;IS THE DATA TYPE SPECIFIER LEGAL? BEQ EQPBAD ;ZERO IS NOT ALLOWED, BAD PARAMETERS CMP #T.RSDN,I.PRM+10(R3) ;IS THE DATA TYPE SPECIFIER LEGAL? BHIS CKBFLN ;IF HIS, YES...FINISH CHECKS AND QUEUE REQUEST BR EQPBAD ;BAD PARAMETERS .ENDC ;B$$MAP .SBTTL . QPRPR - READ AFTER PROMPT .SBTTL . QPRTT - READ WITH TERMINATOR TABLE ; ;+ ; **-QPRPR - READ AFTER PROMPT REQUEST (IO.RPR) ; **-QPRTT - READ WITH TERMINATOR TABLE REQUEST (IO.RTT) ;- ; .ENABL LSB QPRPR:: MOV I.PRM+12(R3),R1 ;GET PROMPT BUFFER SIZE BR 5$ ;CONTINUE IN COMMON QPRTT:: MOV #32.,R1 ;LENGTH OF TABLE IS FIXED AT 32. BYTES BIT #1,I.PRM+10(R3) ;CHECK FOR WORD ALIGNMENT BNE EQPSPC ;CAN'T HAVE BYTE ALIGNED BUFFER 5$: MOV #CKBFR,-(SP) ;READ CHECK AND LOCK CMP R1,$CPMXB ;CAN IT BE BUFFERED IN CPRBUF? BHI 10$ ;NOPE, CONTINUE CMP I.PRM+4(R3),$CPMXB ;CAN PRIMARY BE BUFFERED ALSO? BHI 10$ ;NOPE, CAN'T DO IT MOV #CPBFR,(SP) ;BUFFERING ROUTINE MOV R1,-(SP) ;SAVE LENGTH MOV R3,-(SP) ;AND I/O PACKET ADD I.PRM+4(R3),R1 ;GET TOTAL LENGTH ADD #177,R1 ;ROUND TO NEXT BLOCK, ADD ONE BLOCK ASH #-6,R1 ;MAKE INTO 32-WORD BLOCK CLR R0 ;NO FLAGS CALL $CPALO ;ALLOCATE A BLOCK OF CPRBUF MOV (SP)+,R3 ;RESTORE I/O PACKET MOV (SP)+,R1 ;RESTORE REAL LENGTH BCC 9$ ;GOT CPR PACKET, CONTINUE ;SO MUCH FOR BUFFERING MOV #CKBFR,(SP) ;GO BACK TO READ CHECK AND LOCK BR 10$ 9$: MOV R0,R2 ;SET CPR BIAS MOV R0,2(SP) ;STORE CPR PACKET FOR POSSIBLE ERROR RECOVERY MOV #MAP6+100,R4 ;OFFSET TO START BUFFER ADD I.PRM+4(R3),R4 ;PUT AFTER PRIMARY BUFFER 10$: MOV I.PRM+10(R3),R0 ;GET ADDRESS OF BUFFER MOV R1,I.PRM+14(R3) ;SET LENGTH IN I/O PACKET CALL @(SP)+ ;CHECK READ ACCESS AND RELOCATE TABLE ADDRESS BCS IOFIN ;IF CS, CHECK FAILED...RETURN WITH THE ERROR MOV R1,I.PRM+10(R3) ;SAVE FIRST WORD OF ADDRESS DOUBLE WORD MOV R2,I.PRM+12(R3) ;SAVE SECOND WORD OF ADDRESS DOUBLE WORD MOV #21,R4 ;INDICATE TWO BUFFERS BR CKBFLN ;CHECK BUFFER LENGTH AND QUEUE THE REQUEST .DSABL LSB .SBTTL . QPRLB - READ LOGICAL BLOCK ; ;+ ; **-QPRLB - NORMAL READ REQUEST (IO.RLB) ;- ; QPRLB:: MOV #1,R4 ;INDICATE ONE BUFFER BR CKBFLN ;CHECK BUFFER LENGTH AND QUEUE THE REQUEST .PAGE .SBTTL . ERROR HANDLING ; ; EQPPRI - RETURN PRIVILEGE VIOLATION ERROR. ; EQPPRI: MOV #IE.PRI&377,R2 ;SET ERROR CODE FOR PRIVILEGE VIOLATION BR IOFIN ;FINISH I/O REQUEST ; ; EQPBAD - RETURN ERROR FOR BAD PARAMETERS. ; EQPBAD:: MOV #IE.BAD&377,R2 ;SET ERROR FOR BAD PARAMETER SPECIFIED BR IOFIN ;FINISH REQUEST ; ; EQPSPC - RETURN ERROR BECAUSE OF INVALID BUFFER SPECIFICATION. ; EQPSPC: MOV #IE.SPC&377,R2 ;SET ERROR FOR ILLEGAL BUFFER SPECIFICATION IOFIN:: MOV (SP)+,R0 ;POSSIBLE CPR PACKET BEQ 10$ ;NOPE MOV R3,-(SP) MOV R2,-(SP) ;SAVE ERROR STATUS MOV I.TCB(R3),R3 ; GET TCB. BIC #TS.RSW,T.STAT(R3) ; CANCEL RESOURCE WAIT, IF ANY. CALL $CPDEA ;DEALLOCATE PACKET MOV (SP)+,R2 ;RESTORE ERROR STATUS MOV (SP)+,R3 10$: MOV R2,R0 ;MOVE ERROR STATUS FOR IOFIN CLR R1 ;CLEAR SECOND WORD OF IOSB SEC ;INDICATE FAILURE RETURN ;RETURN TO XXDRV .PAGE .SBTTL . CKBFLN - FINAL BUFFER LENGTH CHECK ; ; CKBFLN - CHECK THAT BUFFER LENGTH IS WITHIN (1,8K-64) BYTES ; BUFFER IN CPRBUF IF POSSIBLE ; CKBFLN: MOV I.PRM+4(R3),R1 ;GET LENGTH OF TRANSFER REQUEST BEQ EQPSPC ;IF EQ, RETURN ZERO BUFFER LENGTH ERROR CMP R1,#20000-100 ;IS BUFFER BIGGER THAN 8128. BYTES? BHI EQPBAD ;IF HI, BUFFER IS TOO BIG...RETURN ERROR CMP R1,$CPMXB ;BUFFER IN CPR PACKET? BHI QUEUE ;NOPE, JUST QUEUE THE PACKET TST (SP) ;CPR PACKET ALREADY EXIST? BNE 20$ ;YES, USE IT CMP #1,R4 ;IS THERE JUST ONE BUFFER? BNE QUEUE ;NO. IF PROMPT COULD NOT BE BUFFERED, DON'T ;BUFFER PRIMARY EITHER ADD #177,R1 ;ROUND TO NEXT BLOCK, ADD ONE FOR HEADER ASH #-6,R1 ;MAKE INTO 32 WORD BLOCK CLR R0 ;NO FLAGS MOV R3,-(SP) ;SAVE I/O PACKET CALL $CPALO ;ALLOCATE A BLOCK MOV (SP)+,R3 ;RESTORE I/O PACKET BCS QUEUE ;IF CAN'T GET ONE, FORGET BUFFERING MOV R0,(SP) ;SAVE IN CASE OF ERROR CMPB #,I.FCN+1(R3) ;WAS THIS A READ? BEQ 20$ ;YES, DON'T BLXIO EMPTY BUFFER MOV R4,-(SP) ;SAVE BUFFER FLAGS MOV R3,-(SP) ;SAVE I/O PACKET MOV #MAP6+100,R4 ;OFFSET TO BUFFER IN CPR PACKET MOV I.PRM+4(R3),R0 ;GET LENGTH OF TRANSFER REQUEST MOV I.PRM(R3),R1 ;BIAS OF USER BUFFER MOV I.PRM+2(R3),R2 ;OFFSET OF USER BUFFER SUB #MAP6-MAP5,R2 ;MAKE INTO APR5 OFFSET MOV 4(SP),R3 ;BIAS OF CPR PACKET CALL $BLXIO ;COPY BUFFER INTO PACKET MOV (SP)+,R3 ;RESTORE I/O PACKET MOV (SP)+,R4 ;RESTORE FLAGS BR 30$ ;FINISH UP 20$: MOV @#KISAR6,R0 ;SAVE CURRENT MAPPING MOV (SP),@#KISAR6 ;MAP CPR PACKET MOV I.PRM(R3),MAP6+P$LUN+32 ;SAVE BIAS MOV I.PRM+2(R3),MAP6+P$LUN+34 ;AND OFFSET MOV R0,@#KISAR6 ;RESTORE APR6 MAPPING 30$: MOV (SP),I.PRM(R3) ;BIAS OF PACKET MOV #100,I.PRM+2(R3);OFFSET OF BUFFER IN PACKET .SBTTL QUEUE - PLACE I/O REQUEST PACKET INTO TERMINAL QUEUE ; ; R4 NOW CONTAINS BUFFER FLAG. SAVE THE FLAG IN I.LN2+1 OF THE I/O PACKET. ; SET THE HIGH BIT IF THE CPR PACKET IS ALREADY ALLOCATED ; QUEUE:: TST (SP)+ ;WAS THERE A CPR PACKET ALLOCATED? BEQ 10$ ;NOPE, CONTINUE BIS #200,R4 ;MARK THE BUFFER POINTER FLAGS 10$: ADD #U.TSTA,R5 ;POINT UCB POINTER TO THE FIRST STATUS WORD MOV I.LN2(R3),R0 ;GET POINTER TO 2ND LUN WORD SUB #,R0 ;GET OFFSET INTO LUT ASR R0 ;DIVIDE BY 4 (4 BYTES PER LUN ENTRY) ASR R0 ; INC R0 ;LUN NUMBERS START AT 1 MOVB R0,I.LN2(R3) ;RETURN TO LUN FIELD IN I/O PACKET MOVB R4,I.LN2+1(R3) ;SAVE BUFFER FLAG BYTE MOV U.SCB-U.TSTA(R5),R0 ;GET I/O QUEUE LISTHEAD MOV R3,R1 ;GET PACKET POINTER CALLR $QINSP ;INSERT PACKET AND RETURN .PAGE .SBTTL . QPATT/QPDET - ATTACH/DETACH REQUESTS ; ;+ ; **-QPATT - ATTACH TERMINAL REQUEST (IO.ATT) ; **-QPDET - DETACH TERMINAL REQUEST (IO.DET) ; ; ENTRY POINT "QPATT" PERFORMS UNSOLICITED INPUT AST ADDRESS ADJUSTMENT FOR ; SUPERVISOR MODE LIBRARIES. ; ; INPUTS: ; R3 => I/O PACKET FOR ATTACH/DETACH REQUEST ; R5 => UCB FOR THE TERMINAL ; ; OUTPUTS: ; R3 => I/O PACKET TO BE QUEUED ; R4 = BUFFER INDICATOR BYTE ; ; REGISTERS MODIFIED: R0, R1, R2 ;- ; QPATT:: ; ; CHECK FOR UCB OF TERMINAL WHICH IS NOT TI: NOR HT377: ; DO NOT ALLOW ATTACH ; MOV I.UCB(R3),R2 ;GET UCB ADDRESS FOR ATTACH MOV I.TCB(R3),R4 ;GET TCB OF TASK BITB #TF.AST,I.FCN(R3) ;ATTACH FOR UNSOLICITED INPUT AST? BEQ 35$ ;IF EQ NO MOV I.PRM+4(R3),-(SP) ;GET CONTROL-C AST ADDRESS BEQ 10$ ;IF EQ, NONE...CHECK OTHER AST ADDRESS BIT #TF.XCC,I.FCN(R3) ;CONFLICTING SUBFUNCTION CODE? BNE 40$ ;IF NE, YES...RETURN AN ERROR 10$: BIS I.PRM(R3),(SP)+ ;"OR" IN UNSOLICITED INPUT AST ADDRESS BEQ 50$ ;IF EQ, NEITHER ADDRESS SPECIFIED...ERROR 30$: MOV I.PRM(R3),R2 ;GET ALL CHARACTER AST ADDRESS CALL $CALTA ;ADJUST FOR SUPER/USER MODE MOV R2,I.PRM(R3) ;AND PUT IT BACK MOV I.PRM+4(R3),R2 ;GET CONTROL C AST ADDRESS CALL $CALTA ;ADJUST FOR SUPER/USER MODE MOV R2,I.PRM+4(R3) ;AND PUT IT BACK 35$: BIS #TS.RSW,T.STAT(R4) ; BLOCK TASK TO MAKE IT SYNCHRONOUS. CLR R4 ;INDICATE NO BUFFERS JMP QUEUE 40$: TST (SP)+ ;CLEAN STACK 50$: JMP EQPSPC ;RETURN WITH ERROR QPDET:: MOV I.UCB(R3),R2 ;GET UCB ADDRESS CLR U.ATT(R2) ;CLEAR ATTACH CLR R4 ;INDICATE NO BUFFERS JMP QUEUE ;QUEUE THE REQUEST .PAGE .SBTTL . QPSPC - "SPECIAL" REQUESTS ; ;+ ; **-QPSPC - HANDLE "SPECIAL" REQUESTS (IO.GTS/SF.GMC/SF.SMC) ; ; THIS ROUTINE CHECKS PARAMETERS FOR THE "GET TERMINAL SUPPORT" AND THE ; "GET/SET MULTIPLE CHARACTERISTICS" FUNCTIONS. THE USER BUFFER FOR THESE ; REQUESTS MUST BE WORD-ALIGNED. ; ; INPUTS: ; R3 => I/O PACKET FOR THE REQUEST ; R5 => UCB FOR THE TERMINAL ; ; OUTPUTS: ; R3 => I/O PACKET TO BE QUEUED ; R4 = BUFFER INDICATOR BYTE ; ; REGISTERS MODIFIED: R0, R1, R2 ;- ; QPSPC:: MOV I.PRM+2(R3),R1 ;GET BUFFER ITS LENGTH BIT #1,R1 ;ODD? BEQ 1$ ;IF EQ, IT'S A FULL WORD LENGTH JMP EQPSPC ;RETURN ERROR FOR LENGTH NOT WORD-ALIGNED 1$: MOV R1,I.PRM+4(R3) ;PUSH LENGTH DOWN ONE FIELD CMP I.FCN(R3),#IO.GTS ;IO.GTS? ;GET TERMINAL DRIVER SUPPORT REQUEST? BEQ 2$ ;IF EQ, YES CMP I.FCN(R3),#SF.GMC ;GET MULTIPLE CHARACTERISTICS REQUEST? BNE 3$ ;IF NE, NO ; ; THIS IS A GET INFORMATION REQUEST. TASK MUST BE BLOCKED FOR SYNCHRONIZAION, ; BUFFER MUST HAVE WRITE ACCESS. ; 2$: MOV I.TCB(R3),R0 ;GET TCB ADDRESS OF TASK BIS #TS.RSW,T.STAT(R0) ;BLOCK TASK TO MAKE IT SYNCHRONOUS MOV #CKBFW,-(SP) ;ASSUME A WRITE CHECK, NO BUFFERING CMP R1,$CPMXB ;BUFFER THIS IN CPR PACKET? BHI 10$ ;NOPE, ACCESS DIRECTLY MOV #CPBFW,(SP) ;BUFFER REQUEST, WRITE ACCESS, WORD ALIGNED BR 6$ ;ALLOCATE CPRBUF PACKET 3$: ; ; SANITY CHECK - IS THIS A LEGAL QIO TYPE FOR US? ; CMP I.FCN(R3),#SF.SMC ;SET MULTIPLE CHARACTERISTICS REQUEST? BEQ 4$ ;IF EQ YES, CONTINUE JMP EQPIFC ;IF NE, NO...RETURN ILLEGAL FUNCTION ERROR 4$: ; ; WRITE REQUEST. READ ACCESS ONLY NECESSARY FOR BUFFER, MUST BE OWN TI OR PRIV ; TASK. ; MOV I.TCB(R3),R2 ;GET ISSUING TASK'S TCB CMP T.UCB(R2),R5 ;IS THIS TERMINAL HIS TI:? BEQ 5$ ;IF EQ, YES...REQUEST IS LEGAL BIT #T3.PRV,T.ST3(R2) ;IS THE TASK PRIVILEGED? BNE 5$ ;IF NE YES, OK JMP EQPPRI ;IF EQ, NO...CAN'T ALLOW USER TO DO THIS 5$: MOV #CKBFRW,-(SP) ;SET UP FOR READ CHECK, WORD ALIGNED CMP R1,$CPMXB ;BUFFER THIS IN CPR PACKET? BHI 10$ ;NOPE, ACCESS DIRECTLY MOV #CPBFRW,(SP) ;BUFFER REQUEST, READ ACCESS, WORD ALIGNED 6$: CLR R0 ;NO FLAGS FOR ALLOCATE ADD #177,R1 ;ROUND UP, AND ADD ONE BLOCK ASH #-6,R1 ;ROUND TO NEAREST 32 WORD BLOCK MOV R3,-(SP) ;SAVE I/O PACKET CALL $CPALO ;ALLOCATE A BLOCK OF CPRBUF MOV (SP)+,R3 ;RESTORE I/O PACKET BCC 7$ ;GOT ONE ;CAN'T GET CPR PACKET, FORGET BUFFERING MOV #CKBFRW,(SP) ;GO BACK TO CHECK AND LOCK CMP I.FCN(R3),#SF.SMC ;SET MULTIPLE CHARACTERISTICS REQUEST? BEQ 10$ ;IF EQ YES, CONTINUE MOV #CKBFW,(SP) ;NOPE, WRITE ACCESS REQUIRED BR 10$ ;GO ADDRESS CHECK 7$: MOV R0,R2 ;MOVE THE CPRBUF BIAS MOV R0,2(SP) ;STORE CPR PACKET FOR POSSIBLE ERROR RECOVERY MOV #MAP6+100,R4 ;OFFSET TO START BUFFER MOV I.PRM+2(R3),R1 ;RESTORE THE LENGTH OF THE TRANSFER 10$: MOV I.PRM(R3),R0 ;GET ADDRESS OF BUFFER CALL @(SP)+ ;ADDRESS CHECK BUFFER AND RELOCATE OR BUFFER IT BCC 20$ ;IF CC, NO ERROR JMP IOFIN ;IF ERROR, FINISH UP WITH ERROR CODE IN R0 20$: MOV #1,R4 ;SHOW ONE BUFFER MOV R1,I.PRM(R3) ;PUT BIAS IN I/O PACKET MOV R2,I.PRM+2(R3) ; AND DISPLACEMENT JMP QUEUE ;QUEUE REQUEST ; ; EQPIFC - RETURN AN ERROR DUE TO ILLEGAL FUNCTION CODE OR INVALID MODIFIERS. ; EQPIFC:: MOV #IE.IFC&377,R2 ;SET ERROR FOR ILLEGAL FUNCTION CODE OR MODIFIER JMP IOFIN ;FINISH OFF THE REQUEST (RESTORE MAPPING ALSO) .PAGE .SBTTL . QPHNG - HANGUP REQUEST ; ;+ ; **-QPHNG - HANGUP REQUEST (IO.HNG) ; ; THIS ROUTINE CHECKS AN IO.HNG REQUEST. A NON-PRIVILEGED TASK CAN HANG ; UP ONLY ITS "TI:" LINE. PRIVILEGED TASKS CAN HANG UP ANY LINE. A HANGUP ; REQUEST, LIKE AN IO.WBT OR GET CHARACTERISTICS, BREAKS THROUGH THE QUEUE. ; ; INPUTS: ; R3 => I/O PACKET FOR THE REQUEST ; R5 => UCB FOR THE TERMINAL ; ; OUTPUTS: ; R3 => I/O PACKET TO BE QUEUED ; R4 = BUFFER INDICATOR BYTE ; ; REGISTERS MODIFIED: R0 ;- ; QPHNG:: MOV I.TCB(R3),R0 ;GET ISSUING TASK'S TCB CMP T.UCB(R0),R5 ;IS THIS TERMINAL HIS TI:? BEQ 10$ ;IF EQ, YES...ALLOW THE HANGUP BIT #T3.PRV,T.ST3(R0) ;IS THE TASK PRIVILEGED? BNE 10$ ;IF NE, YES...ALLOW THE HANGUP JMP EQPPRI ;RETURN PRIVILEGE VIOLATION ERROR 10$: CLR R4 ;INDICATE NO BUFFERS JMP QUEUE ;QUEUE THE REQUEST .END